home *** CD-ROM | disk | FTP | other *** search
Text File | 1987-10-14 | 6.2 KB | 210 lines | [TEXT/ttxt] |
- {
- Name: “FileName” -- a HyperCard "XFCN" (External Function) resource
-
- Written By: Steve Maller
- Apple Computer Training Support
- Copyright © 1987 Apple Computer
- AppleLink: MALLER1
- Saturday, August 22, 1987
-
- Language: MPW Pascal
-
- To build: pascal FileName.p
- link -m ENTRYPOINT -rt XFCN=913 -sn Main=FileName ∂
- -t STAK -c WILD ∂
- FileName.p.o ∂
- hd:dev:mpw:libraries:Interface.o ∂
- hd:dev:mpw:PLibraries:Paslib.o ∂
- -o "hd:hyper:hypercard stacks:TestXFCN"
-
- Usage: FileName("fileType") -- "fileType" is optional
-
- Examples: FileName("STAK") -- limits list to HyperCard Stacks
- FileName("TEXT") -- limits list to text files
- FileName("APPL") -- limits list to applications
- FileName() -- lists ALL files
-
- Result: The full pathname of the selected file.
- For example, if you selected the file "Address Stack" which is
- in the folder "My Stacks" in the folder "HyperCard" on the
- disk "HD" the result is:
- HD:HyperCard:My Stacks:Address Stack
- If the user clicks “Cancel” an empty string is returned.
-
- Warning: A word of caution: the Mac's file system can NOT accept
- pathnames longer than 255 characters. Be careful...
-
- Script
- Example: on mouseUp
- put FileName("TEXT") into theFile
- if theFile is not empty then
- open file theFile
- read from file theFile for 2000
- put it into bkgnd field 1
- close file theFile
- end if
- end mouseUp
-
- Why? You must access files in HyperCard by their full pathname.
- Unfortunately, HyperCard offers you no clear way of finding
- out what that full name is. If files are on a hard disk, it
- can be a real pain to remember the entire pathname. This
- function simplifies that task for both the stackware developer
- and the end user.
-
- Thanks to: Ted Kaehler, Dan Winkler, and Bill Atkinson - my hero!
-
- }
-
- {$S FileName }
-
- UNIT Snoopy_Vs_TheRedBaron; { obviously this is irrelevant }
-
- INTERFACE
-
- USES
- {$LOAD HD:Hyper:XCMDs:PasSymDump}
- MemTypes, QuickDraw, OSIntf, ToolIntf, PackIntf, HyperXCmd;
-
- PROCEDURE EntryPoint(paramPtr: XCmdPtr);
-
- IMPLEMENTATION
-
- TYPE
- Str31 = String[31];
-
- PROCEDURE FileName(paramPtr: XCmdPtr);
- FORWARD;
-
- PROCEDURE EntryPoint(paramPtr: XCmdPtr);
-
- BEGIN
- FileName(paramPtr);
- END;
-
- PROCEDURE FileName(paramPtr: XCmdPtr);
-
- VAR
- myWDPB: WDPBPtr; { some variants of the same animal }
- myCPB: CInfoPBPtr;
- myPB: HParmBlkPtr;
- fullPathName: Str255;
- numTypes: Integer;
- reply: SFReply;
- typeList: SFTypeList;
-
- {$I XCmdGlue.inc }
-
- FUNCTION TheyChoseAFile: Boolean;
-
- VAR
- pt: Point;
-
- BEGIN
- TheyChoseAFile := FALSE;
- pt.v := 60;
- pt.h := 82;
- SFGetFile(pt, '', NIL, numTypes, typeList, NIL, reply);
- { have 'em pick a file }
- IF reply.good THEN { if they didn't choose Cancel }
- BEGIN
- TheyChoseAFile := TRUE;
- fullPathName := reply.fName; { start the ball rolling }
- END;
- END;
-
- PROCEDURE BuildThePathName;
-
- VAR
- name: Str255;
- err: Integer;
-
- BEGIN
- name := ''; { start with an empty name }
- myPB^.ioNamePtr := @name; { we want the Volume name }
- myPB^.ioCompletion := pointer(0);
- myPB^.ioVRefNum := reply.vRefNum; { returned from SFGetFile }
- myPB^.ioVolIndex := 0; { use the vRefNum and name }
- err := PBHGetVInfo(myPB, FALSE); { fill in the Volume info }
- IF err <> noErr THEN
- Exit(FileName);
-
- { Now we need the Working Directory (WD) information because we're going
- to step backwards from the file through all of the the folders until
- we reach the root directory }
-
- myWDPB^.ioVRefNum := reply.vRefNum; { this got set to 0 above }
- myWDPB^.ioWDProcID := 0; { use the vRefNum }
- myWDPB^.ioWDIndex := 0; { we want ALL directories }
- err := PBGetWDInfo(myWDPB, FALSE); { do it }
- IF err <> noErr THEN
- Exit(FileName);
-
- myCPB^.ioFDirIndex := - 1; { use the ioDirID field only }
- myCPB^.ioDrDirID := myWDPB^.ioWDDirID;{ info returned above }
- err := PBGetCatInfo(myCPB, FALSE); { do it }
- IF err <> noErr THEN
- Exit(FileName);
-
- { Here starts the real work - start to climb the tree by continually
- looking in the ioDrParId field for the next directory above until we
- fail... }
-
- myCPB^.ioDrDirID := myCPB^.ioDrParId; { the first folder}
- fullPathName := Concat(myCPB^.ioNamePtr^, ':', reply.fName);
- REPEAT
- myCPB^.ioDrDirID := myCPB^.ioDrParId;
- err := PBGetCatInfo(myCPB, FALSE); { the next level }
-
- { Be careful of an error returned here - it means the user chose a file
- on the desktop level of this volume. If this is the case, just stop
- here and return "VolumeName:FileName", otherwise loop until failure }
- IF err = noErr THEN
- fullPathName := Concat(myCPB^.ioNamePtr^, ':', fullPathName);
-
- UNTIL err <> noErr;
-
- END; { PROCEDURE BuildThePathName }
-
- BEGIN { PROCEDURE FileName }
-
- { First we allocate some memory in the heap for the parameter block. This
- could in theory work on the stack, but in reality it makes no difference
- as we're entirely modal (ugh) here... }
-
- fullPathName := '';
-
- myCPB := CInfoPBPtr(NewPtr(SizeOf(HParamBlockRec)));
- IF ord4(myCPB) <= 0 THEN
- Exit(FileName); { Rats! Bill didn't leave enough room }
- myWDPB := WDPBPtr(myCPB); { icky Pascal type coercions follow }
- myPB := HParmBlkPtr(myCPB);
-
- numTypes := 1; { for SFGetFile }
- WITH paramPtr^ DO
- BEGIN
- IF paramCount = 0 THEN
- numTypes := - 1 { FileName() - get all files }
- ELSE
- BlockMove(params[1]^, @typeList[0], 4);
- { FileName("TYPE") }
-
- IF TheyChoseAFile THEN
- BuildThePathName;
-
- { PasToZero is very interesting - it is a HyperTalk command
- that you can actually call from OUTSIDE of HyperCard.
- You need it because HyperCard uses C format strings with
- no length byte; they are terminated by a null byte. They are
- actually HANDLES to C format strings. Nice work, Dan! }
-
- returnValue := PasToZero(fullPathName);
-
- END; { WITH paramPtr^ DO }
-
- DisposPtr(pointer(myCPB)); { Clean Up Your Heap! }
-
- END; { PROCEDURE FileName }
-
- END.
-